#ifdef linux

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include "yuv2rgb.h"

static int convert_yuv_to_rgb_pixel(int y, int u, int v)
{
	unsigned int pixel32 = 0;
	unsigned char *pixel = (unsigned char *)&pixel32;
	int r, g, b;

	r = y + (1.402 * (v - 128));
	g = y - (0.34413 * (u - 128)) - (0.71414 * (v - 128));
	b = y + (1.772 * (u - 128));

	r = r < 0 ? 0 : r;
	g = g < 0 ? 0 : g;
	b = b < 0 ? 0 : b;

    pixel[0] = b > 0xff ? 0xff : r;
	pixel[1] = g > 0xff ? 0xff : g;
    pixel[2] = r > 0xff ? 0xff : b;

	return pixel32;
}

int convert_yuv_to_rgb888_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
{
	unsigned int i, out = 0;
	unsigned int pixel32;
	int y0, u, y1, v;
	unsigned int len = width * height * 2;

	for (i = 0; i < len; i += 4) {
		y0 = yuv[i + 0];
		u  = yuv[i + 1];
		y1 = yuv[i + 2];
		v  = yuv[i + 3];

		pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
		rgb[out++] = pixel32 & 0xff;
		rgb[out++] = (pixel32 >> 8) & 0xff;
		rgb[out++] = (pixel32 >> 16) & 0xff;
        out++;

		pixel32 = convert_yuv_to_rgb_pixel(y1, u, v);
		rgb[out++] = pixel32 & 0xff;
		rgb[out++] = (pixel32 >> 8) & 0xff;
		rgb[out++] = (pixel32 >> 16) & 0xff;
        out++;
	}

	return 0;
}

#if 0
int main(int argc, char **argv)
{
	int src_fd, fd, ret;
	void *yuvptr = NULL;
	void *rgbptr = NULL;
	struct stat file_info;

	src_fd = open(argv[1], O_RDONLY);
	if (src_fd < 0) {
		perror("Load yuv img");
		goto err_0;
	}
	
	fd = open("rgb.rgb", O_RDWR | O_CREAT | O_TRUNC, 0666);
	if (fd < 0) {
		perror("Create rgb");
		goto err_1;
	}

	stat(argv[1], &file_info);
	printf("Image file size is %ld Bytes\n", file_info.st_size);

	yuvptr = mmap(NULL, file_info.st_size, PROT_READ, MAP_SHARED, src_fd, 0);
	if (yuvptr == NULL) {
		perror("mmap yuv");
		goto err_2;
	}

	ret = ftruncate(fd, file_info.st_size << 1);
	if (ret < 0) {
		perror("trunc");
		goto err_3;
	}

	rgbptr = mmap(NULL, file_info.st_size << 1, PROT_WRITE, MAP_SHARED, fd, 0);
	if (rgbptr == NULL) {
		perror("mmap rgb");
		goto err_3;
	}

	convert_yuv_to_rgb_buffer(yuvptr, rgbptr, 640, 480);

	munmap(rgbptr, file_info.st_size << 1);
	munmap(yuvptr, file_info.st_size);
	close(fd);
	close(src_fd);

	return 0;
	
err_3:
	munmap(yuvptr, file_info.st_size);
err_2:
	close(fd);
err_1:
	close(src_fd);
err_0:
	return -1;
}
#endif

#ifdef __cplusplus
}
#endif

#endif /* linux */
